/*
 * Copyright (C) 2009  Sylvain Maucourt (smaucourt@gmail.com)
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 *
 */
package net.sylvek.where;

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.os.IBinder;
import android.preference.PreferenceManager;
import android.util.Log;

import com.restfb.DefaultFacebookClient;
import com.restfb.FacebookClient;
import com.restfb.Parameter;
import com.restfb.types.FacebookType;

import org.json.JSONObject;

public class UpdateLocationService extends Service implements LocationListener {

    private LocationManager locationManager;

    private final static long MIN_TIME = 0;

    private final static float MIN_DIST = 50;

    private FacebookClient fbClient;

    private SharedPreferences pref;

    private final static String LAST_LATITUDE = "net.sylvek.where.last_latitude";

    private final static String LAST_LONGITUDE = "net.sylvek.where.last_longitude";

    private final static String PERMISSION_CHECK = "net.sylvek.where.permission_auto";

    public static final Criteria getCriteria()
    {
        Criteria criteria = new Criteria();
        criteria.setAccuracy(Criteria.ACCURACY_COARSE);
        criteria.setAltitudeRequired(false);
        criteria.setBearingRequired(false);
        criteria.setCostAllowed(false);
        criteria.setPowerRequirement(Criteria.POWER_LOW);
        criteria.setSpeedRequired(false);

        return criteria;
    }

    @Override
    public IBinder onBind(Intent arg0)
    {
        throw new UnsupportedOperationException();
    }

    @Override
    public void onCreate()
    {
        super.onCreate();

        pref = PreferenceManager.getDefaultSharedPreferences(this);
        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        String accessToken = pref.getString(Where.STORED_ACCESS_TOKEN, null);
        if (accessToken == null) {
            locationManager.removeUpdates(this);
            stopSelf();
        } else {
            fbClient = new DefaultFacebookClient(accessToken);
        }
    }

    @Override
    public void onStart(Intent intent, int startId)
    {
        super.onStart(intent, startId);

        String provider = locationManager.getBestProvider(getCriteria(), true);
        if (provider != null) {
            locationManager.requestLocationUpdates(provider, MIN_TIME, MIN_DIST, this);
        } else {
            stopSelf();
        }
    }

    @Override
    public void onLocationChanged(final Location location)
    {
        String lastLatitude = pref.getString(LAST_LATITUDE, "0");
        String lastLongitude = pref.getString(LAST_LONGITUDE, "0");
        Boolean permissionCheck = pref.getBoolean(PERMISSION_CHECK, false);
        String distance = pref.getString(Where.PREF_UPDATE_DISTANCE, "5"); // 5km by default

        boolean needUpdate = WhereUtils.distanceKm(Double.parseDouble(lastLatitude), Double.parseDouble(lastLongitude),
                location.getLatitude(), location.getLongitude()) >= Double.parseDouble(distance);

        if (needUpdate) {
            Log.d("update.location", "updating");
            try {
                JSONObject result = SylvekClient.update(FbClient.NAME, FbClient.ID, location.getLatitude(),
                        location.getLongitude(), true);
                if (result.getBoolean("success")) {
                    WhereUtils.sentNotification(this, getString(R.string.update_location_service));
                    pref.edit().putString(LAST_LATITUDE, Double.toString(location.getLatitude())).putString(LAST_LONGITUDE,
                            Double.toString(location.getLongitude())).commit();

                    if (permissionCheck) {
                        try {
                            String url = WhereUtils.getCurrentStaticLocationUrl(UpdateLocationService.this, location);
                            String address = WhereUtils.getAddress(UpdateLocationService.this, location);
                            String tinyurl = WhereUtils.getTinyLink(url);
                            String message = getString(R.string.currently_here, address, tinyurl);
                            fbClient.publish("me/feed", FacebookType.class, Parameter.with("message", message));
                        } catch (Exception e) {
                            Log.e("update.status", e.getMessage());
                        }
                    }
                }
            } catch (Exception e) {
                Log.e("update.location", e.getMessage());
            }
        } else {
            Log.d("update.location", "no necessary");
        }

        locationManager.removeUpdates(this);
        stopSelf();
    }

    @Override
    public void onProviderDisabled(String provider)
    {
    }

    @Override
    public void onProviderEnabled(String provider)
    {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras)
    {
    }
}
